package stream;

import org.junit.Test;
import ref.Employee;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @Author com.alibaba.lizhen
 * @Date 2021/3/24 11:05 上午
 * @Version 1.0
 * @Description
 *  * 创建stream
 *  * 中间操作（过滤、map）
 *  * 终止操作
 */
public class StreamApiTest2 {
    List<Employee> emps = Arrays.asList(
            new Employee(1, "张三1"),
            new Employee(1, "张三1"),
            new Employee(2, "张三2"),
            new Employee(2, "张三2"),
            new Employee(3, "张三3"),
            new Employee(4, "张三4"),
            new Employee(5, "张三5"),
            new Employee(6, "张三6"),
            new Employee(7, "张三7")
    );

    /**
     * Stream的中间操作:
     * filter：接收 Lambda ，从流中排除某些元素，返回新的流
     * limit：截断流，使其元素不超过给定数量
     * skip(n)：跳过元素，返回一个舍弃了前n个元素的流；若流中元素不足n个，则返回一个空流；与 limit(n) 互补
     * distinct：筛选，通过流所生成的 hashCode() 与 equals() 取除重复元素
     * <p>
     * TODO 注意，只有流执行终止操作，中间操作才会一次性起作用，否则中间操作不起作用，即为 "惰性求值"
     */
    @Test
    public void test2() {
        Stream<Employee> stream = emps.stream()
                .filter(employee -> {
                    System.out.println("中间操作！");
                    return employee.getId() > 1;
                });
        //TODO 如果没有终止操作，filter不会执行！
//        stream.forEach(System.out::println);


        //筛选 过滤  去重

        emps.stream()
                .filter(e -> {
                    System.out.println("测试短路!");
                    return e.getId() > 0;
                })
                // TODO  短路！！！达到满足不再内部迭代
                .limit(4)
                .skip(1)
                // 需要流中的元素重写hashCode和equals方法
                .distinct()
                .forEach(System.out::println);

    }


    /**
     * Stream的中间操作:映射
     * map：接收 Lambda ，将元素转换为其他形式或提取信息；接受一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素
     * flatMap：接收一个函数作为参数，将流中每一个值都换成另一个流，然后把所有流重新连接成一个流
     */
    @Test
    public void test3() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc");

        //map
        list.stream()
                .map((str) -> str.toUpperCase())
//                .map(String::toUpperCase)
                .forEach(System.out::println);
        emps.stream()
                .map(Employee::getName)
                .forEach(System.out::println);

        System.out.println("----------------");
        //flatMap前置
        Stream<Stream<Character>> streams = list.stream()
                //filterCharacter的入参是str，返回值是stream
                //而map的返回值本身就是一个stream，所以是双重流
                .map(StreamApiTest2::filterCharacter);
        streams.forEach((stream) -> {
            stream.forEach(System.out::println);
        });
        System.out.println("----------------");

        //flatMap：将多个流整合到一个流
        Stream<Character> stream = list.stream()
                //filterCharacter的入参是str，返回值是stream
                //而map的返回值本身就是一个stream，所以是双重流
                .flatMap(StreamApiTest2::filterCharacter);
        stream.forEach(System.out::println);
    }

    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for (char c : str.toCharArray()) {
            list.add(c);
        }

        return list.stream();
    }


    /**
     * 排序
     * sorted()：自然排序
     * Comparable：自然排序,使用compareTo
     * sorted(Comparator c)：定制排序，使用compare
     */
    @Test
    public void test4() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        list.stream()
                .sorted() //comparaTo()
                .forEach(System.out::println);

        emps.stream()
                //compare()
                .sorted((e1, e2) -> {
                    if (e1.getId() == (e2.getId())) {
                        return e1.getName().compareTo(e2.getName());
                    } else {
                        return e1.getId() - (e2.getId());
                    }
                })
                .forEach(System.out::println);
    }

}
